package ua.edu.sumdu.j2se.roman.lab1.model;

import ua.edu.sumdu.j2se.roman.lab1.domain.ArrayTaskList;
import ua.edu.sumdu.j2se.roman.lab1.domain.LinkedTaskList;
import ua.edu.sumdu.j2se.roman.lab1.domain.Task;
import ua.edu.sumdu.j2se.roman.lab1.domain.TaskList;
import ua.edu.sumdu.j2se.roman.lab1.exceptions.FileSerializationException;
import ua.edu.sumdu.j2se.roman.lab1.service.FileSerializationTasksService;
import ua.edu.sumdu.j2se.roman.lab1.service.TasksService;

import java.util.Date;
import java.util.Observable;

/**
 * Author: Radko Roman.
 */

/**
 * This class describes directions to store data in memory, writing data to the memory and reading from it.
 *
 */
public class TasksModelImpl extends Observable implements TasksModel {

    private TaskList listOfTasks;
    private TasksService tasksService;

    /**
     * Load from the file list of task.
     *
     */
    public TasksModelImpl () {
        this.tasksService = new FileSerializationTasksService();
        try {
            listOfTasks = tasksService.loadList();
        } catch (FileSerializationException e) {
            listOfTasks = new ArrayTaskList();
        }
    }

    /**
     * Gets the first nearest date of the task from now.
     *
     * @return  nearest date from now
     */
    @Override
    public Date getFirstTaskDateFromNow() {
        Date now = new Date();
        Date result = null;
        for(Task t : listOfTasks) {
            Date cur = t.getStartTime();
            if (cur.compareTo(now) >= 0) {
                if (result == null) {
                    result = cur;
                } else if (cur.before(result)) {
                    result = cur;        
                }
            }
        }
        return result;
    }

    /**
     * Gets task by date.
     *
     * @param key   date
     * @return      task
     */
    @Override
    public TaskList getTasksByDate(Date key) {
        TaskList result = new LinkedTaskList();
        for (Task t : listOfTasks) {
            if (t.getStartTime().equals(key)) {
                result.add(t);
            }
        }
        return result;
    }

    /**
     * Adds task to the list.
     *
     * @param task  to be added
     */
    @Override
    public void addTask(Task task) {
        listOfTasks.add(task);
        setChanged();
        notifyObservers();
    }

    /**
     * Gets list of the tasks.
     *
     * @return task list
     */
    @Override
    public TaskList getTasks() {
        return listOfTasks;
    }

    /**
     * Gets task by title.
     *
     * @param title of the task
     * @return      task
     */
    @Override
    public Task getTaskByTitle(String title) {
        for (Task t : listOfTasks) {
            if (t.getTitle().equals(title)) {
                return t;
            }    
        }
        return null;
    }

    /**
     * Delete task from the task list.
     *
     * @param task  task to be removed from the list
     */
    @Override
    public void deleteTask(Task task) {
        listOfTasks.remove(task);
        setChanged();
        notifyObservers();
    }

    /**
     * Save any changes of the model on the hard disc.
     *
     * @throws FileSerializationException arises when could not create file with specified path
     */
    @Override
    public void saveData() throws FileSerializationException {
        tasksService.saveList(listOfTasks);
    }

    /**
     * This method must return listeners any changes of the model.
     *
     * @return changed model
     */
    @Override
    public Observable observable() {
        return this;
    }

    /**
     * Postpone task at the some date.
     *
     * @param task      planned task
     * @param nextTime  next time reminders
     */
    @Override
    public void postponeTask(Task task, Date nextTime) {
        task.setTime(nextTime);
        setChanged();
        notifyObservers();
    }
}
